package com.j1ay.forum.config.security;
import com.j1ay.forum.filter.CustomAuthenticationFilter;
import com.j1ay.forum.filter.JwtAuthenticationTokenFilter;
import com.j1ay.forum.filter.VerifyCodeFilter;
import com.j1ay.forum.handler.JwtAccessDeniedHandler;
import com.j1ay.forum.handler.JwtAuthenticationEntryPoint;
import com.j1ay.forum.handler.JwtAuthenticationSuccessHandler;
import com.j1ay.forum.handler.LoginFailureHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

/**
 * @Author J1ay
 * @Date 2021/12/18 15:56
 * @Description 权限管理配置
 */

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    @Resource
    private JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler;

    @Resource
    private LoginFailureHandler loginFailureHandler;

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    // 自定义的Jwt Token过滤器
    @Bean
    public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
        return new JwtAuthenticationTokenFilter();
    }

    @Bean
    public VerifyCodeFilter verifyCodeFilterBean() throws Exception {
        return new VerifyCodeFilter();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(
                "/swagger-ui.html/**",
                // swagger api json
                "/webjars/springfox-swagger-ui/**",
                "/configuration/**",
                "/v2/api-docs",
                "/swagger-resources",
                "/druid/**"
        );
        web.ignoring().antMatchers(  "/images/**");
    }


    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .formLogin()
                .and()
                //token的验证方式不需要开启csrf的防护
                .csrf().disable()
                // 自定义认证失败类
                .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
//                // 自定义权限不足处理类
                .accessDeniedHandler(new JwtAccessDeniedHandler())
                .and()
                //设置无状态的连接,即不创建session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                .antMatchers( "/api/user/login","/api/user/code", "/api/user/register", "/api/user/logout").permitAll()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                //配置允许匿名访问的路径
                .anyRequest().authenticated();

        // 解决跨域问题
        httpSecurity.cors().and().csrf().disable();

        httpSecurity
                .addFilterBefore(verifyCodeFilterBean(), UsernamePasswordAuthenticationFilter.class);
        //配置自己的jwt验证过滤器
        httpSecurity
                .addFilterAt(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
        // 改变form表单提交格式，转为json
        httpSecurity
                .addFilterAt(customAuthenticationFilterBean(), UsernamePasswordAuthenticationFilter.class);


        httpSecurity.headers().cacheControl();



    }

    CustomAuthenticationFilter customAuthenticationFilterBean() throws Exception {
        CustomAuthenticationFilter filter = new CustomAuthenticationFilter();
        //自定义认证成功处理器
        filter.setAuthenticationSuccessHandler(jwtAuthenticationSuccessHandler);
        // 自定义失败拦截器
        filter.setAuthenticationFailureHandler(loginFailureHandler);
        // 自定义登录拦截URI
        filter.setFilterProcessesUrl("/api/user/login");

        // 重用WebSecurityConfigurerAdapter配置的AuthenticationManager
        filter.setAuthenticationManager(authenticationManagerBean());
        return filter;
    }


    public static void main(String[] args) {
        //加密策略 MD5 不安全 彩虹表  MD5 加盐
        String j1ay = new BCryptPasswordEncoder().encode("j1ay");
        System.out.println(j1ay);
    }
}
